﻿using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Wicture.DbRESTFul;

namespace Wicture.QPZS.EPC.Models
{
    public class VinServiceRule
    {
        public string ServiceName { get; set; }

        public List<PrefixRule> PrefixRules { get; set; }
        public List<RegexRule> RegexRules { get; set; }

        private static List<VinServiceRule> vinServiceRules;
        public static List<VinServiceRule> GetVinServiceRules()
        {
            if (vinServiceRules == null) { Load(); }
            return vinServiceRules;
        }

        public static void Load()
        {
            var path = Path.Combine(Directory.GetCurrentDirectory(), "vin_rules.json");
            var content = File.ReadAllText(path);
            vinServiceRules = JArray.Parse(content).ToObject<List<VinServiceRule>>();
        }

        public static (string serviceName, string brandCode) MatchPrefixRule(string vin)
        {
            foreach (var rule in GetVinServiceRules())
            {
                var brandCode = rule.MatchPrefex(vin);
                if (!string.IsNullOrEmpty(brandCode))
                {
                    return (rule.ServiceName, brandCode);
                }
            }

            return (null, null);
        }

        public static (string serviceName, string brandCode) MatchRegexRule(string vin)
        {
            foreach (var rule in GetVinServiceRules().Where(r => r.RegexRules != null))
            {
                foreach (var r in rule.RegexRules)
                {
                    var brandCode = r.Match(vin);
                    if (!string.IsNullOrEmpty(brandCode))
                    {
                        return (rule.ServiceName, brandCode);
                    }
                }
            }

            return (null, null);
        }

        private string MatchPrefex(string vin)
        {
            var matchedRule = PrefixRules?.FirstOrDefault(r => r.SeedArray.Any(s => vin.StartsWith(s)));
            return matchedRule?.BrandCode;
        }
    }

    public class PrefixRule : VinRule
    {

    }

    public class RegexRule
    {
        public string Regex { get; set; }
        public List<VinRule> Rules { get; set; }
        public SeedRange SeedRange { get; set; }

        private Regex r;
        public Regex R
        {
            get
            {
                if (r == null) r = new Regex(Regex);
                return r;
            }
        }

        public string Match(string vin)
        {
            if (!R.IsMatch(vin)) return null;

            var seed = vin.Substring(SeedRange.Start, SeedRange.Length);

            var matchedRule = Rules?.FirstOrDefault(r => r.SeedArray.Any(s => seed.Equals(s)));
            var brandCode =  matchedRule?.BrandCode;
            if(string.IsNullOrEmpty(brandCode))
            {
                LoggerManager.Logger.LogError(new System.Exception(), $"Vin Seed Not Matched:{vin}");
            }
            return brandCode;
        }
    }

    public class SeedRange
    {
        public int Start { get; set; }
        public int Length { get; set; }
    }

    public class VinRule
    {
        public string BrandCode { get; set; }
        public string Seeds { get; set; }

        private string[] seeds;
        public string[] SeedArray
        {
            get
            {
                if (seeds == null)
                {
                    seeds = Seeds.Split(',').ToArray();
                }

                return seeds;
            }
        }
    }
}
